var crypto = require('../utils/crypto');
var express = require('express');
var db = require('../utils/db');
var http = require('../utils/http');
var user_mgr = require("./usermgr");
var room_mgr = require("./roommgr");
var app = express();

var hallIp = null;
var config = null;
var rooms = {};
var serverMap = {};
var roomIdOfUsers = {};
var log4js = require('log4js');
var log = log4js.getLogger("roomService");

app.use(log4js.connectLogger(log4js.getLogger("httpAccess"), { level: 'auto' }));
//设置跨域访问
app.all('*', function (req, res, next) {
	res.header("Access-Control-Allow-Origin", "*");
	res.header("Access-Control-Allow-Headers", "X-Requested-With");
	res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
	res.header("X-Powered-By", ' 3.2.1');
	res.header("Content-Type", "application/json;charset=utf-8");
	next();
});

app.get('/register_gs', function (req, res) {
	var id = req.query.id;
	var ip = req.ip;
	if (ip.indexOf("::ffff:") != -1) {
		ip = ip.substr(7);
		if (hallIp == null) {
			hallIp = "::ffff:" + config.HALL_IP;
		}
	}
	if (hallIp == null) {
		hallIp = config.HALL_IP;
	}

	var port = req.query.port;
	var httpPort = req.query.httpPort;
	var load = req.query.load;
	id = ip + ":" + port;

	if (serverMap[id]) {
		var info = serverMap[id];
		if (info.port != port
			|| info.httpPort != httpPort
			|| info.ip != ip
		) {
			log.debug("duplicate gsid:" + id + ",addr:" + ip + "(" + httpPort + ")");
			http.send(res, 1, "duplicate gsid:" + id);
			return;
		}
		info.load = load;
		http.send(res, 0, "ok", { ip: ip });
		return;
	}
	serverMap[id] = {
		ip: ip,
		id: id,
		port: port,
		httpPort: httpPort,
		load: load
	};
	http.send(res, 0, "ok", { ip: ip });
	//log.debug("game server registered.\n\tid:" + id + "\n\taddr:" + ip + "\n\thttp port:" + httpPort + "\n\tsocket port:" + port);

	// var reqdata = {
	// 	serverid: id,
	// 	sign: crypto.md5(id + config.ROOM_PRI_KEY)
	// };
	//获取服务器信息
	// http.get(ip, httpPort, "/get_server_info", reqdata, function (ret, data) {
	// 	if (ret && data.errcode == 0) {
	// 		for (var i = 0; i < data.userroominfo.length; i += 2) {
	// 			var userId = data.userroominfo[i];
	// 			var roomId = data.userroominfo[i + 1];
	// 		}
	// 	}
	// 	else {
	// 		log.warn(data.errmsg);
	// 	}
	// });
});

function chooseServer() {
	var serverinfo = null;
	for (var s in serverMap) {
		var info = serverMap[s];
		if (serverinfo == null) {
			serverinfo = info;
		}
		else {
			if (serverinfo.load > info.load) {
				serverinfo = info;
			}
		}
	}
	return serverinfo;
}

exports.createRoom = function (account, userId, roomConf, fnCallback) {
	var serverinfo = chooseServer();
	if (serverinfo == null) {
		fnCallback(101, null);
		return;
	}
	db.get_user_data(account, function (data) {
		if (data != null) {
			console.log("create room ip port ", userId, data.gems, serverinfo.ip, serverinfo.httpPort);
			var reqdata = { userid: userId, gems: data.gems, conf: roomConf };
			reqdata.sign = crypto.md5(userId + hallIp + roomConf + data.gems + config.ROOM_PRI_KEY);
			http.get(serverinfo.ip, serverinfo.httpPort, "/create_room", reqdata, function (ret, data) {
				if (ret) {
					if (data.errcode == 0) {
						var room_info = {
							uuid: null,
							id: data.roomid,
							base_info: null,
							create_time: Date.now(),
							num_of_turns: 1,
							next_button: 0,
							ip: serverinfo.ip,
							port: serverinfo.port,
							maxGames: 0,
							costGems: 0,
						};
						room_mgr.storeNewRoom(room_info);
						fnCallback(0, data.roomid);
						log.debug("create room success! ", data.roomid);
					} else {
						fnCallback(data.errcode, null);
					}
				} else {
					fnCallback(102, null);
				}
			});
		} else {
			fnCallback(103, null);
		}
	});
};

exports.enterRoom = function (userId, name, roomId, fnCallback) {
	var reqdata = {
		userid: userId,
		name: name,
		roomid: roomId
	};
	reqdata.sign = crypto.md5(userId + name + roomId + hallIp + config.ROOM_PRI_KEY);

	var checkRoomIsRuning = function (serverinfo, roomId, callback) {
		var sign = crypto.md5(roomId + hallIp + config.ROOM_PRI_KEY);
		http.get(serverinfo.ip, serverinfo.httpPort, "/is_room_runing", { roomid: roomId, sign: sign }, function (ret, data) {
			if (ret) {
				if (data.errcode == 0 && data.runing == true) {
					callback(true);
				}
				else {
					log.debug("checkRoomIsRuning callback false 1");
					callback(false);
				}
			}
			else {
				log.debug("checkRoomIsRuning callback false 2");
				callback(false);
			}
		});
	}

	var enterRoomReq = function (serverinfo) {
		http.get(serverinfo.ip, serverinfo.httpPort, "/enter_room", reqdata, function (ret, data) {
			log.debug(data);
			if (ret) {
				if (data.errcode == 0) {
					db.set_room_id_of_user(userId, roomId, function (ret) {
						log.debug("set_room_id_of_user call back , set room id == " + roomId);
						user_mgr.setRoomIdOfUser(roomId, userId);
						fnCallback(0, {
							ip: serverinfo.ip,
							port: serverinfo.port,
							token: data.token
						});
					});
				}
				else {
					log.warn(data.errmsg);
					fnCallback(data.errcode, null);
				}
			}
			else {
				log.warn("enterRoomReq call back -1");
				fnCallback(-1, null);
			}
		});
	};

	var chooseServerAndEnter = function (serverinfo) {
		serverinfo = chooseServer();
		if (serverinfo != null) {
			log.debug("enterRoomReq function begin 2");
			enterRoomReq(serverinfo);
		}
		else {
			log.debug("chooseServerAndEnter call back -1");
			fnCallback(-1, null);
		}
	}

	db.get_room_addr(roomId, function (ret, ip, port) {
		console.log("get_room_addr roomId , ip , port", roomId, ip, port);
		if (ret) {
			var id = ip + ":" + port;
			var serverinfo = serverMap[id];
			log.debug("id == " + id + "serverinfo == " + serverinfo);
			if (serverinfo != null) {
				checkRoomIsRuning(serverinfo, roomId, function (isRuning) {
					if (isRuning) {
						log.debug("enterRoomReq function begin 1");
						enterRoomReq(serverinfo);
					}
					else {
						log.debug("chooseServerAndEnter function begin");
						chooseServerAndEnter(serverinfo);
					}
				});
			}
			else {
				log.debug("chooseServerAndEnter function begin");
				chooseServerAndEnter(serverinfo);
			}
		}
		else {
			log.warn("call back -1 not get room addr from db!");
			fnCallback(-1, null);
		}
	});
};

exports.start = function ($config) {
	config = $config;
	app.listen(config.ROOM_PORT);
	log.info("room service is listening on port " + config.ROOM_PORT);

	room_mgr.initRoomInfo();
	//setInterval(room_mgr.update,2000);
};